package com.happok.onlineclass.usermanagement.user.service;

import cn.hutool.core.bean.BeanUtil;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.happok.common.exception.BusinessException;
import com.happok.common.page.PageResponse;
import com.happok.onlineclass.usermanagement.common.dto.Contants;
import com.happok.onlineclass.usermanagement.common.dto.IdDTO;
import com.happok.onlineclass.usermanagement.common.exception.SendFailedException;
import com.happok.onlineclass.usermanagement.feign.service.CustomFormService;
import com.happok.onlineclass.usermanagement.feign.service.ResourceCenterService;
import com.happok.onlineclass.usermanagement.setting.dto.EmailSettingInfoDTO;
import com.happok.onlineclass.usermanagement.setting.dto.FunctionClassifyEnum;
import com.happok.onlineclass.usermanagement.setting.dto.FunctionVerifyDTO;
import com.happok.onlineclass.usermanagement.setting.po.SmsPO;
import com.happok.onlineclass.usermanagement.setting.service.SettingService;
import com.happok.onlineclass.usermanagement.setting.utils.EmailUtil;
import com.happok.onlineclass.usermanagement.setting.utils.SmsUtil;
import com.happok.onlineclass.usermanagement.user.dataobject.UserDO;
import com.happok.onlineclass.usermanagement.user.dto.*;
import com.happok.onlineclass.usermanagement.verifycode.service.VerifyCodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 接口分类                        yapi 分类文件夹
 * 功能说明
 *
 * @author : chenac
 * @module 项目名称/模块名          yapi 项目组/子项目
 * @date : 2021/7/15 11:01
 */
@Slf4j
@Service
public class ManageUserServiceImpl implements ManageUserService {

    @Autowired
    private UserDaoService userDaoService;

    @Autowired
    private ResourceCenterService resourceCenterService;

    @Autowired
    private CustomFormService customFormService;

    @Autowired
    private SettingService settingService;

    @Autowired
    private VerifyCodeService verifyCodeService;

    public final static Pattern emailPattern = Pattern.compile("^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$");
    public final static Pattern phonePattern = Pattern.compile("^[1]([3-9])[0-9]{9}$");

    @Override
    public IdDTO addUser(String user, AddUserDTO addUserDTO) throws Exception {
        if (ObjectUtils.isEmpty(addUserDTO.getPhone())
                && ObjectUtils.isEmpty(addUserDTO.getEmail())) {
            throw new BusinessException(1, "用户账号（手机或邮箱）不能为空");
        }
        boolean paramsError = (addUserDTO.getHeadPortraitId() != null
                && addUserDTO.getHeadPortraitUrl() == null)
                || (addUserDTO.getHeadPortraitId() == null
                && addUserDTO.getHeadPortraitUrl() != null);
        if (paramsError) {
            throw new BusinessException("参数异常");
        }
        UserDO userDO = new UserDO();
        BeanUtil.copyProperties(addUserDTO, userDO);
        userDO.setForcePassword(true);
        userDaoService.addUser(userDO);
        if (!ObjectUtils.isEmpty(addUserDTO.getExtendData())) {
            String recordId = customFormService.addFormRecord(userDO.getId(), Contants.HTTP_CUSTOM_FORM_USER_INFO, addUserDTO.getExtendData());
            UserDO updatedUserDO = new UserDO();
            updatedUserDO.setId(userDO.getId());
            updatedUserDO.setExtendInfoId(recordId);
            userDaoService.updateUserById(updatedUserDO);
        }
        if (!ObjectUtils.isEmpty(addUserDTO.getHeadPortraitId())) {
            resourceCenterService.addResourcesReference(String.valueOf(addUserDTO.getHeadPortraitId()));
        }
        // 发送通知
        EmailSettingInfoDTO emailSetting = settingService.getEmailSetting(false);
        SmsPO smsSetting = settingService.getSmsSettingEnable();
        FunctionVerifyDTO resetPasswordSetting = settingService.getFunctionSetting(FunctionClassifyEnum.ADD_USER);
        String account = "";
        if (!ObjectUtils.isEmpty(userDO.getPhone()) && !ObjectUtils.isEmpty(userDO.getEmail())) {
            account = userDO.getPhone() + "或" + !ObjectUtils.isEmpty(userDO.getEmail());
        } else if (!ObjectUtils.isEmpty(userDO.getPhone())) {
            account = userDO.getPhone();
        } else {
            account = userDO.getEmail();
        }
        // 发送通知，如果失败。按照成功进行处理
        if (!ObjectUtils.isEmpty(userDO.getPhone()) &&
                settingService.smsSettingEnable(smsSetting) &&
                !ObjectUtils.isEmpty(resetPasswordSetting.getSmsVerify().getTemplateCode())) {
            try {
                SmsUtil.sendSmsAddUser(smsSetting.getAccessKeyId(), smsSetting.getAccessKeySecret(), smsSetting.getDomainName(), smsSetting.getSmsSign(),
                        userDO.getPhone(), account, addUserDTO.getPassword(), resetPasswordSetting.getSmsVerify().getTemplateCode());
            } catch (ClientException e) {
                throw new SendFailedException(10, userDO.getId().toString());
            }
        }
        if (!ObjectUtils.isEmpty(userDO.getEmail()) &&
                settingService.emailSettingEnable(emailSetting) &&
                !ObjectUtils.isEmpty(resetPasswordSetting.getEmailVerify().getTopic()) &&
                !ObjectUtils.isEmpty(resetPasswordSetting.getEmailVerify().getContent())) {
            try {
                EmailUtil.sendEmailAddUser(emailSetting.getServer(), emailSetting.getAccount(),
                        !ObjectUtils.isEmpty(emailSetting.getPassword()) ? emailSetting.getPassword() : emailSetting.getAuthorizationCode(),
                        userDO.getEmail(), account, addUserDTO.getPassword(), resetPasswordSetting.getEmailVerify());
            } catch (Exception e) {
                throw new SendFailedException(10, userDO.getId().toString());
            }
        }
        return new IdDTO(userDO.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserByUserId(String user, Integer userId, ManageUpdateUserDTO manageUpdateUserDTO) throws Exception {
        userDaoService.isUserExist(userId);
        boolean paramsError = (manageUpdateUserDTO.getHeadPortraitId() != null
                && manageUpdateUserDTO.getHeadPortraitUrl() == null)
                || (manageUpdateUserDTO.getHeadPortraitId() == null
                && manageUpdateUserDTO.getHeadPortraitUrl() != null);
        if (paramsError) {
            throw new BusinessException("参数异常");
        }
        if (!ObjectUtils.isEmpty(manageUpdateUserDTO.getEmail())) {
            if (!emailPattern.matcher(manageUpdateUserDTO.getEmail()).matches()) {
                throw new BusinessException("邮箱格式不正确");
            }
        }
        if (!ObjectUtils.isEmpty(manageUpdateUserDTO.getPhone())) {
            if (!phonePattern.matcher(manageUpdateUserDTO.getPhone()).matches()) {
                throw new BusinessException("手机号格式不正确");
            }
        }
        UserDO userDO = userDaoService.getUserDetailById(userId);
        if (manageUpdateUserDTO.getPhone() == ""
                && manageUpdateUserDTO.getEmail() == "") {
            throw new BusinessException("参数异常");
        }

        String recordId = null;
        if (!ObjectUtils.isEmpty(manageUpdateUserDTO.getExtendData())) {
            if (!ObjectUtils.isEmpty(userDO.getExtendInfoId())) {
                customFormService.updateFormRecord(user, userId, userDO.getExtendInfoId(), Contants.HTTP_CUSTOM_FORM_USER_INFO, manageUpdateUserDTO.getExtendData());
            } else {
                recordId = customFormService.addFormRecord(userId, Contants.HTTP_CUSTOM_FORM_USER_INFO, manageUpdateUserDTO.getExtendData());
            }
        }
        userDaoService.updateUserByUserId(userId, recordId, manageUpdateUserDTO);
        if (manageUpdateUserDTO.getHeadPortraitId() != null) {
            if (!ObjectUtils.isEmpty(userDO.getHeadPortraitId())
                    && !userDO.getHeadPortraitId().equals(manageUpdateUserDTO.getHeadPortraitId())) {
                resourceCenterService.deleteResources(userDO.getHeadPortraitId());
                if (manageUpdateUserDTO.getHeadPortraitId() != "") {
                    resourceCenterService.addResourcesReference(manageUpdateUserDTO.getHeadPortraitId());
                }
            } else if (ObjectUtils.isEmpty(userDO.getHeadPortraitId()) && manageUpdateUserDTO.getHeadPortraitId() != "") {
                resourceCenterService.addResourcesReference(manageUpdateUserDTO.getHeadPortraitId());
            }
        }
    }

    @Override
    public void enableUserByUserId(Integer userId, EnableUserDTO enableUserDTO) {
        userDaoService.isUserExist(userId);
        UserDO userDO = userDaoService.getUserDetailById(userId);
        if (Contants.ADMIN_EMAIL.equals(userDO.getEmail())
                && !enableUserDTO.getEnable()) {
            throw new BusinessException(4, "管理员不能被禁用");
        }
        userDaoService.enableUserByUserId(userId, enableUserDTO);
    }

    @Override
    public void checkAccount(CheckAccountDTO checkAccountDTO) {
        if (ObjectUtils.isEmpty(checkAccountDTO.getPhone())
                && ObjectUtils.isEmpty(checkAccountDTO.getEmail())) {
            throw new BusinessException("参数异常");
        }
        userDaoService.checkAccount(checkAccountDTO);
    }

    @Override
    public PageResponse<ListUserDTO> listUser(ListUserParamDTO listUserParamDTO) throws URISyntaxException {
        List<Integer> includeIds = new ArrayList<>();
        if (!ObjectUtils.isEmpty(listUserParamDTO.getExtendData())) {
            listUserParamDTO.getExtendData().put("page", listUserParamDTO.getPage());
            listUserParamDTO.getExtendData().put("size", listUserParamDTO.getSize());
            includeIds = customFormService.listFormRecord(Contants.HTTP_CUSTOM_FORM_USER_INFO, listUserParamDTO.getExtendData());
        }
        PageResponse<ListUserDTO> pageResponse = new PageResponse<>();
        if (ObjectUtils.isEmpty(includeIds)
                && !ObjectUtils.isEmpty(listUserParamDTO.getExtendData())) {
            pageResponse.setTotal(0);
            pageResponse.setPage(listUserParamDTO.getPage());
            pageResponse.setSize(listUserParamDTO.getSize());
            return pageResponse;
        } else {
            if (!ObjectUtils.isEmpty(listUserParamDTO.getUserIds())) {
                includeIds.addAll(listUserParamDTO.getUserIds());
            }
            listUserParamDTO.setUserIds(includeIds);
            IPage<UserDO> userDOPage = userDaoService.listUser(listUserParamDTO);
            pageResponse.setTotal(userDOPage.getTotal());
            pageResponse.setPage(userDOPage.getCurrent());
            pageResponse.setSize(userDOPage.getSize());
            pageResponse.setResult(BeanUtil.copyToList(userDOPage.getRecords(), ListUserDTO.class));
        }
        return pageResponse;
    }

    @Override
    public List<UserSimpleDTO> listUser(List<Integer> userIds) {
        return userDaoService.listUser(userIds);
    }

    @Override
    public List<ListUserDTO> listUserBasicInfo(List<Integer> userIds) {
        return userDaoService.listUserBasicInfo(userIds);
    }

    @Override
    public UserDetailDTO getUserDetailById(Integer userId) throws URISyntaxException {
        userDaoService.isUserExist(userId);
        UserDO userDO = userDaoService.getUserDetailById(userId);
        UserDetailDTO userDetailDTO = new UserDetailDTO();
        BeanUtil.copyProperties(userDO, userDetailDTO);
        if (!ObjectUtils.isEmpty(userDO.getExtendInfoId())) {
            Map<String, Object> extendData = customFormService.getFormRecord(userDO.getExtendInfoId(), Contants.HTTP_CUSTOM_FORM_USER_INFO);
            userDetailDTO.setExtendData(extendData);
        }
        return userDetailDTO;
    }

    @Override
    public void resetPassword(ResetPwdDTO resetPwdDTO) {
        userDaoService.isUserExist(resetPwdDTO.getUserId());
        EmailSettingInfoDTO emailSetting = settingService.getEmailSetting(false);
        Boolean emailEnable = settingService.emailSettingEnable(emailSetting);
        SmsPO smsSetting = settingService.getSmsSettingEnable();
        Boolean smsEnable = settingService.smsSettingEnable(smsSetting);
        FunctionVerifyDTO resetPasswordSetting = settingService.getFunctionSetting(FunctionClassifyEnum.RESET_PASSWORD);
        UserDO userDetail = userDaoService.getUserDetailById(resetPwdDTO.getUserId());
        String pwd = "";
        // 如果新密码不为空，则直接修改密码并发送通知
        if (!ObjectUtils.isEmpty(resetPwdDTO.getNewPassword())) {
            pwd = resetPwdDTO.getNewPassword();
        } else {
            // 如果新密码为空，根据配置判断新密码是否必须输入
            if ((!emailEnable &&
                    !smsEnable) ||
                    !settingService.functionEnable(resetPasswordSetting)) {
                throw new BusinessException("新密码不能为空");
            }
            pwd = verifyCodeService.getIntegerRandom();
        }
        UserDO updateUser = new UserDO();
        updateUser.setId(resetPwdDTO.getUserId());
        updateUser.setPassword(pwd);
        updateUser.setForcePassword(true);
        userDaoService.updateUserById(updateUser);
        // 发送通知，如果失败。按照成功进行处理
        if (!ObjectUtils.isEmpty(userDetail.getPhone()) &&
                settingService.smsSettingEnable(smsSetting) &&
                !ObjectUtils.isEmpty(resetPasswordSetting.getSmsVerify().getTemplateCode())) {
            try {
                SmsUtil.sendSmsResetPwd(smsSetting.getAccessKeyId(), smsSetting.getAccessKeySecret(), smsSetting.getDomainName(), smsSetting.getSmsSign(),
                        userDetail.getPhone(), pwd, resetPasswordSetting.getSmsVerify().getTemplateCode());
            } catch (ClientException e) {
                log.error("重置密码发送通知异常");
                throw new SendFailedException(10, "通知发送失败");
            }
        }
        if (!ObjectUtils.isEmpty(userDetail.getEmail()) &&
                settingService.emailSettingEnable(emailSetting) &&
                !ObjectUtils.isEmpty(resetPasswordSetting.getEmailVerify().getTopic()) &&
                !ObjectUtils.isEmpty(resetPasswordSetting.getEmailVerify().getContent())) {
            try {
                EmailUtil.sendEmailResetPwd(emailSetting.getServer(), emailSetting.getAccount(),
                        !ObjectUtils.isEmpty(emailSetting.getPassword()) ? emailSetting.getPassword() : emailSetting.getAuthorizationCode(),
                        userDetail.getEmail(), pwd, resetPasswordSetting.getEmailVerify());
            } catch (Exception e) {
                log.error("重置密码发送通知异常");
                throw new SendFailedException(10, "通知发送失败");
            }
        }
    }
}